#pragma once

#include "MathCommon.h"
#include <type_traits>
#include <cmath>

class WHENGINE_API CMathBase
{
public:
	static double Pi;
	static double HalfPi;
	static double PiDevide180;
	static double _180DevidePi;
	static Float EqualError;

	template<typename T>
	static T Abs(T InValue)
	{
		if(InValue<0)
		{
			return -InValue;
		}
		return InValue;
	}

	static float Sqrt(float InValue);
	static double Sqrt(double InValue);

	static float Mod(float A,float B);

	//InvSqrt might faster than 1/sqrt(InValue)  in the future
	//@return  1/sqrt(x)
	static float InvSqrt(float InValue);
	static double InvSqrt(double InValue);

	static float DegreeToRadian(float InDegree);
	static double DegreeToRadian(double InDegree);

	static float RadianToDegree(float InRadian);
	static double RadianToDegree(double InRadian);

	static float Sin(float InRadian);
	static double Sin(double InRadian);

	static float Asin(float InValue);
	static double Asin(double InValue);


	static float Cos(float InRadian);
	static double Cos(double InRadian);

	static float Acos(float InRadian);
	static double Acos(double InRadian);

	static float Tan(float InRadian);
	static double Tan(double InRadian);

	//return randian
	static float Atan(float InValue);
	static double Atan(double InValue);

	static float Atan2(float Y,float X);
	static double Atan2(double Y, double X);

	template<typename T1,typename T2>
	static T1 Min(T1 A, T2 B)
	{
		return (A < B) ? A : (T1)B;
	}

	template<typename T1,typename T2>
	static T1 Max(T1 A, T2 B)
	{
		return (A > B) ? A : B;
	}

	static Float Clamp(Float A, Float InMin, Float InMax)
	{
		return Min(Max(A, InMin), InMax);
	}

	static bool Equal(const Float A, const Float B);

	static Float Pow(Float A, Float B); 

	template<typename T>
	requires std::is_floating_point<T>::value
	static T Floor(T InValue)
	{
		return (T)floor(InValue);
	}

	template<typename T>
	requires std::is_floating_point<T>::value
	static T Ceil(T InValue)
	{
		return (T)ceil(InValue);
	}


	
    //返回A/B,不会出现除0错误
    //@Error  B的绝对值的最小值
    static double SafeDivide(double A,double B, double Error=0.000001 );
};
